/**
 * Beyondo licenses this file to You under the GNU General Public
 * License, Version 3.0 (the "License");
 * 
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.gnu.org/licenses/lgpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.beyondo.sgs.client.impl.sharedutil {
	import com.beyondo.sgs.util.Util;
	import com.beyondo.util.BeyondoByteArray;
	import com.beyondo.util.Equals;
	
/**
 * A utility class for constructing IDs with a self-describing external format.
 * A <code>CompactId</code> is stored in its canonical form, with all leading
 * zero bytes stripped. The external format is designed to be compact if the
 * canonical ID has a small number of bytes.
 * 
 * <p>
 * The first byte of the ID's external form contains a length field of variable
 * size. If the first two bits of the length byte are not #b11, then the size of
 * the ID is indicated as follows:</p>
 * 
 * <ul>
 * <li>#b00: 14 bit ID (2 bytes total)</li>
 * <li>#b01: 30 bit ID (4 bytes total)</li>
 * <li>#b10: 62 bit ID (8 bytes total)</li>
 * </ul>
 *  
 * <p>If the first byte has the following format:</p>
 * <ul>
 * <li>1100<i>nnnn</i></li>
 * </ul>
 * then, the ID is contained in the next <code>8 +  nnnn</code> bytes.
 * 
 * <p>
 * The maximum length of an ID is 23 bytes (if the first byte of the external
 * form has the value <code>11001111</code>).
 */
	public class CompactId implements Equals {
		
		/** The canonical form for this ID. */
		public var bigInteger : BeyondoByteArray;
		
		public function CompactId(id:BeyondoByteArray){
			bigInteger=id;
			bigInteger.position=0;
		}
		
		
		public function toString() : String {
			var n:Number;
			var o:String = "";
			
			for (var i:int=0; i < bigInteger.length;i++) {
				n = Number(bigInteger[i]);
				o += n.toString(16);
			}
			
			return o;
		}
		
		/**
		 * Returns a hash code value for this instance.
		 * 
		 * @return a hash code value for this instance
		 */
		public function hashCode() : int {
			return com.beyondo.sgs.util.Util.CRC32(bigInteger.readUTF());
		}
		
	    
		/**
		 * Returns <code>true</code> if the specified object, <code>obj<code>, is
		 * equivalent to this instance, and returns <code>false</code> otherwise.
		 * An object is equivalent to this instance if it is an instance of
		 * <code>CompactId</code> and has the same representation for its ID.
		 * 
		 * @param obj
		 * 		an object to compare
		 * @return <code>true</code> if <code>obj</code> is equivalent to this
		 * 		instance, and <code>false</code> otherwise
		 */
		public function equals(obj:Equals) : Boolean {
			if (obj is CompactId) {
				if (this == obj) return true;
				var other:CompactId = CompactId(obj);
				for (var i:int=0; i<other.bigInteger.length;i++) {
					if (this.bigInteger[i] != other.bigInteger[i])
						return false;
				}
				return true;
			}
			return false;
		}
	}
}